﻿using System.Diagnostics;
using System.Net.Sockets;
using PacketDotNet;
using SharpPcap;
using 文华财经数据解析_donet8_.entity;
using 文华财经数据解析_donet8_.utils;
using 文华财经数据解析_donet8_.utils.WHDataServer;

namespace 文华财经数据解析_donet8_
{
    internal class Program
    {
        static ushort ReqID = 100;
        static string connectStr33 = "server=172.16.16.33;port=3306;database=info;user=root;password=dyqh@9882;charset=utf8mb4;";

        static Dictionary<ushort, RspKlineData> KlineDataDic = new Dictionary<ushort, RspKlineData>();
        static List<string> dateList = new List<string>();
        static List<string> wpDateList = new List<string>();

        static byte[] catchData = null;

        static AutoResetEvent captureResetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            Capture();
            //StartExe("C:\\wh6大越期货\\mytrader_spqh.exe");
            StartExe("D:\\文华财经\\wh6大越期货\\mytrader_spqh.exe");

            captureResetEvent.WaitOne();

            var whServer = new WHServer(catchData);



            string startDate = DateTime.Now.ToString("20241226");
            string endDate = DateTime.Now.ToString("20250103");
            //等待登陆完成
            Thread.Sleep(3000);

            whServer.OnRspDayKLine = OnRspDayKLine;



            //获取日期列表
            dateList = MyUtil.GetTradeDaysBetween(startDate, endDate);


            string infoWpMaxDate = MyUtil.getInfoWpMaxDate();

            // 将 yyyyMMdd 转换为 DateTime
            DateTime parsedDate = DateTime.ParseExact(endDate, "yyyyMMdd", null);
            // 推前一天
            DateTime previousDate = parsedDate.AddDays(-1);
            wpDateList = MyUtil.GetTradeDaysBetween(infoWpMaxDate, previousDate.ToString("yyyyMMdd"));




            //加权
            string sql = "select scodetype,scodename,business_name,wjj from scode";
            List<Scode> scodes = DBUtil.ExecuteQuery<Scode>(sql, connectStr33);
            for (int i = 0; i < scodes.Count; i++)
            {
                Scode scode = scodes[i];
                string pzdm = scode.scodetype;

                string scodenameStr = scode.scodename;
                string wjj = scode.wjj;

                //Console.WriteLine($"{pzdm} 开始");
                RspKlineData req = new RspKlineData()
                {
                    table = "info",
                    pzdm = pzdm,
                    ReqID = ReqID++,
                    KLines = new List<KlineData>(),
                    filepath = wjj,
                    code = scodenameStr,
                    SumNum = 0,
                    autoResetEvent = new AutoResetEvent(false)
                };
                KlineDataDic.Add(req.ReqID, req);
                whServer.ReqDayKline(req.filepath, req.code, req.ReqID);
                req.autoResetEvent.WaitOne();
                Thread.Sleep(1000);
            }
            Console.WriteLine($"加权数据插入完成");

            //文华指数
            string whzsSql = "select scodetype,scodename,business_name,wjj from scode_wh";
            List<Scode> whzs = DBUtil.ExecuteQuery<Scode>(whzsSql, connectStr33);
            
            for (int i = 0; i < whzs.Count; i++)
            {
                Scode scode = whzs[i];
                string pzdm = scode.scodetype;
                string scodenameStr = scode.scodename;
                string wjj = scode.wjj;
                RspKlineData req = new RspKlineData()
                {
                    table = "info_wh",
                    pzdm = pzdm,
                    ReqID = ReqID++,
                    KLines = new List<KlineData>(),
                    filepath = wjj,
                    code = scodenameStr,
                    SumNum = 0,
                    autoResetEvent = new AutoResetEvent(false)
                };
                KlineDataDic.Add(req.ReqID, req);
                whServer.ReqDayKline(req.filepath, req.code, req.ReqID);
                req.autoResetEvent.WaitOne();
                Thread.Sleep(1000);
            }
            Console.WriteLine($"文华指数数据插入完成");

            //外盘指数
            string whwpSql = "select scodetype,scodename,business_name,wjj from scode_wp";
            List<Scode> whwp = DBUtil.ExecuteQuery<Scode>(whwpSql, connectStr33);
            
            for (int i = 0; i < whwp.Count; i++)
            {
                Scode scode = whwp[i];
                string pzdm = scode.scodetype;
                string scodenameStr = scode.scodename;
                string wjj = scode.wjj;
                RspKlineData req = new RspKlineData()
                {
                    table = "info_wp",
                    pzdm = pzdm,
                    ReqID = ReqID++,
                    KLines = new List<KlineData>(),
                    filepath = wjj,
                    code = scodenameStr,
                    SumNum = 0,
                    autoResetEvent = new AutoResetEvent(false)
                };
                KlineDataDic.Add(req.ReqID, req);
                whServer.ReqDayKline(req.filepath, req.code, req.ReqID);
                req.autoResetEvent.WaitOne();
                Thread.Sleep(1000);
            }
            Console.WriteLine($"外盘指数数据插入完成");

        }

        static void OnRspDayKLine(int allNum, int currNum, List<KlineData> kLines, ushort ReqID)
        {
            if (KlineDataDic.ContainsKey(ReqID))
            {
                var klineData = KlineDataDic[ReqID];
                klineData.SumNum = allNum;
                klineData.KLines.AddRange(kLines);
                string table = klineData.table;

                //Console.WriteLine($"总数据量{allNum} 当前数据量 {currNum}");
                if (klineData.KLines.Count == allNum)
                {
                    int insertNum = 0;


                    List<KlineData> klines = klineData.KLines;
                    for (int i = 0; i < klines.Count; i++)
                    {
                        KlineData data = klines[i];
                        data.pzdm = klineData.pzdm;
                        string date = data.date;


                        if (klineData.table == "info_wp")
                        {
                            if (wpDateList.Contains(date))
                            {
                                MyUtil.InsertDayKLineData(data, table, "23:59:59");
                            }

                        }
                        else
                        {
                            if (dateList.Contains(date))
                            {
                                MyUtil.InsertDayKLineData(data, table, "18:00:00");
                                insertNum++;
                            }
                        }

                    }
                    if (insertNum==0)
                    {
                        Console.WriteLine($"{klineData.pzdm} 未插入");
                    }

                    //Console.WriteLine($"通知主线程继续执行");
                    klineData.autoResetEvent.Set();

                }
            }
            else
            {
                Console.WriteLine($"未找到对应请求ID");
            }

        }


        private static void Device_OnPacketArrival(object sender, PacketCapture e)
        {
            try
            {
                // 解析数据包
                var packet = Packet.ParsePacket(e.GetPacket().LinkLayerType, e.GetPacket().Data);
                var tcpPacket = packet.Extract<TcpPacket>();

                if (tcpPacket != null)
                {
                    // 提取 TCP 数据
                    var payload = tcpPacket.PayloadData;

                    if (payload != null && payload.Length >= 0x0202 + 4)
                    {
                        //0x3a, 0xe6, 0x02, 0x02, 0x08, 0x01
                        if (payload[0] == 0x3a && payload[1] == 0xe6 && payload[2] == 0x02 && payload[3] == 0x02 && payload[4] == 0x08 && payload[5] == 0x01&& payload[78]==0x01)
                        {
                            byte[] loginBT = new byte[0x0202 + 4];
                            Array.Copy(payload, 0, loginBT, 0, 0x0202 + 4);
                            catchData = loginBT;
                            captureResetEvent.Set();
                        }



                        //var data = System.Text.Encoding.Default.GetString(payload);

                        // 检测是否是 HTTP 数据
                        //if (data.StartsWith("GET") || data.StartsWith("POST") || data.StartsWith("HTTP"))
                        //{
                        //    Console.WriteLine("捕获到 HTTP 数据：");
                        //    Console.WriteLine(data);
                        //    Console.WriteLine("----------------------------------------");
                        //}


                        //if (data.StartsWith("GET /ip.asp?key="))
                        //{
                        //    Console.WriteLine(data);
                        //    // 正则表达式匹配 key= 后面的内容
                        //    string pattern = @"key=(?<value>[^&\s]+)";
                        //    Match match = Regex.Match(data, pattern);
                        //
                        //    if (match.Success)
                        //    {
                        //        string keyValue = match.Groups["value"].Value;
                        //
                        //        // 转换为十六进制的 byte[]
                        //        byte[] byteArray = Encoding.UTF8.GetBytes(keyValue);
                        //        catchData = byteArray;
                        //        captureResetEvent.Set();
                        //        //Console.WriteLine($"Extracted value: {keyValue}");
                        //    }
                        //    else
                        //    {
                        //        Console.WriteLine("No match found.");
                        //    }
                        //
                        //
                        //}
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解析数据包时发生错误：{ex.Message}");
            }
        }


        static void Capture()
        {
            // 获取可用的网络接口
            var devices = CaptureDeviceList.Instance;

            if (devices.Count < 1)
            {
                Console.WriteLine("没有检测到网络设备！");
                return;
            }

            // 列出所有设备并选择一个
            Console.WriteLine("可用网络设备：");
            for (int i = 0; i < devices.Count; i++)
            {
                Console.WriteLine($"{i}: {devices[i].Description}");
            }

            // 选择设备 
            //服务端3
            //var device = devices[3];
            //本机 4
            var device = devices[4];
            device.OnPacketArrival += Device_OnPacketArrival;
            device.Open(new DeviceConfiguration() { Mode = DeviceModes.Promiscuous });

            Console.WriteLine($"正在监听设备: {device.Description}...");
            device.StartCapture();
        }



        static void StartExe(string programPath)
        {
            // 要检查和操作的程序的文件路径
            //string programPath = @"C:\Path\To\Your\Program.exe";

            // 确保路径正确
            if (!File.Exists(programPath))
            {
                Console.WriteLine($"错误：文件路径 \"{programPath}\" 不存在！");
                return;
            }

            // 获取程序的名称（不带扩展名）
            string programName = Path.GetFileNameWithoutExtension(programPath);

            // 查找目标程序是否运行
            Process[] runningProcesses = Process.GetProcessesByName(programName);

            if (runningProcesses.Length > 0)
            {
                Console.WriteLine($"{programName} 已经在运行，尝试关闭并重新启动...");

                // 强制关闭所有匹配的进程
                foreach (Process process in runningProcesses)
                {
                    try
                    {
                        process.Kill(); // 强制终止
                        process.WaitForExit(); // 等待退出
                        Console.WriteLine($"进程 {process.ProcessName} (PID: {process.Id}) 已关闭。");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"无法关闭进程 {process.ProcessName} (PID: {process.Id})，原因: {ex.Message}");
                    }
                }
            }
            else
            {
                Console.WriteLine($"{programName} 未在运行，直接启动...");
            }

            // 启动程序
            try
            {
                Process.Start(programPath);
                Console.WriteLine($"{programName} 已成功启动。");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"无法启动 {programName}，原因: {ex.Message}");
            }
        }






    }

    class RspKlineData
    {
        //数据库对应的表格
        public string table;

        public string pzdm;
        public ushort ReqID;
        public int SumNum;
        public List<KlineData> KLines;
        public string filepath;
        public string code;
        public AutoResetEvent autoResetEvent;
    }
}
